#pragma once
#include "Node.h"

template <class TYPE>
class Queue
{
private:
	NODE<TYPE> *front;
	NODE<TYPE> *rear;
	int count;

public:
	Queue(void);
	~Queue(void);
	bool enqueue(TYPE dataIn);
	bool dequeue(TYPE& dataOut);
	bool queueFront(TYPE& dataOut);
	bool queueRear(TYPE& dataOut);
	int queueCount();
	bool emptyQueue();
	bool fullQueue();
	void showQueue();
};

template <class TYPE>
Queue<TYPE>::Queue() {
	front = nullptr;
	rear = nullptr;
	count = 0;
}

template <class TYPE>
bool Queue<TYPE>::enqueue(TYPE dataIn) {
	bool success;
	NODE<TYPE> *newPtr;

	if(!(newPtr = new NODE<TYPE>))
		success = false;
	else{
		newPtr->data = dataIn;
		newPtr->next = nullptr;
		if(count == 0) {
			front = newPtr;
		}
		else {
			rear->next = newPtr;
			
		}
		success = true;
		rear = newPtr;
		count++;
	}
	return success;
}

template <class TYPE>
bool Queue<TYPE>::dequeue(TYPE& dataOut) {
	bool success;
	NODE<TYPE> *temp;
	
	if(count == 0) 
		success = false;
	dataOut = front->data;
	temp = front;
	else if(count == 1) {
		delete temp;
		front = nullptr;
		rear = nullptr;
		count--;
		success = true;
	}
	else {
		front = front->next;
		delete temp;
		count--;
		success = true;
	}
	return success;
}

template <class  TYPE>
bool Queue<TYPE>::queueFront (TYPE& dataOut) {
	bool success;
	if(count == 0) success = false;
	else {
		dataOut = front->data;
		success = true;
	}
	return success;
}

template <class  TYPE>
bool Queue<TYPE>::queueRear(TYPE& dataOut) {
	bool success;
	if(count == 0) success = false;
	else {
		dataOut = rear->data;
		success = true;
	}
	return success;
}

template <class  TYPE>
bool Queue<TYPE>::fullQueue() {
	if(count == 0) return false;

	NODE<TYPE> *newPtr;
	if(!(newPtr = new NODE<TYPE>)) return true;
}

template <class  TYPE>
bool Queue<TYPE>::emptyQueue() {
	if(count == 0) return true;
	else return false;
}

template <class  TYPE>
void Queue<TYPE>::showQueue() {
//	if(count == 0) return;
	NODE<TYPE> *temp = front;
	int i = 0;
	while(temp != nullptr){
		cout<<temp->data<<" ";
		temp = temp->next;
	}
	cout<<rear->data<<endl;
}

template <class  TYPE>
int Queue<TYPE>::queueCount() {
	return count;
}

template <class  TYPE>
Queue<TYPE>::~Queue(void) {
	if(count != 0) {
		NODE<TYPE> *temp;
		temp = rear;
		while (temp)
		{
			rear = rear->next;
			delete temp;
			temp = rear;
		}
		front = nullptr;
		rear = nullptr;
		count = 0;
	}
}